import java.util.*;

public class Planet implements Cloneable {
    // Initializes a planet.

    public Planet(int planetID,
            int owner,
            int numShips,
            int growthRate,
            double x,
            double y) {
        this.planetID = planetID;
        this.owner = owner;
        this.numShips = numShips;
        this.growthRate = growthRate;
        this.x = x;
        this.y = y;
        distances = new HashMap<Integer, Integer>();
    }

    // Accessors and simple modification functions. These should be mostly
    // self-explanatory.
    public int PlanetID() {
        return planetID;
    }

    public int Owner() {
        return owner;
    }

    public int NumShips() {
        return numShips;
    }

    public int GrowthRate() {
        return growthRate;
    }

    public double X() {
        return x;
    }

    public double Y() {
        return y;
    }

    public boolean HasDistance(int planetID) {
        if (distances.containsKey(planetID)) {
            return true;
        }
        return false;
    }

    public boolean HasDistance(Planet p) {
        return HasDistance(p.PlanetID());
    }

    public int GetDistance(int planetID, List<Planet> planets) {
        if (planetID >= 0 && distances.containsKey(planetID)) {
            return distances.get(planetID);
        } else {
            int distance = Distance(planetID, this.planetID, planets);
            if (planetID >= 0) {
                distances.put(planetID, distance);
            }
            return distance;
        }
    }

    public int GetDistance(Planet p) {
        if (p.planetID >= 0 && distances.containsKey(p.planetID)) {
            return distances.get(p.planetID);
        } else {
            int distance = Distance(p, this);
            if (p.planetID >= 0) {
                distances.put(p.planetID, distance);
            }
            return distance;
        }
    }

    // Returns the distance between two planets, rounded up to the next highest
    // integer. This is the number of discrete time steps it takes to get
    // between the two planets.
    public int Distance(int sourcePlanet, int destinationPlanet, List<Planet> planets) {
        Planet source = planets.get(sourcePlanet);
        Planet destination = planets.get(destinationPlanet);
        return Distance(source, destination);
    }

    public int Distance(Planet source, Planet destination) {
        double dx = source.X() - destination.X();
        double dy = source.Y() - destination.Y();
        return (int) Math.ceil(Math.sqrt(dx * dx + dy * dy));
    }

    public void Owner(int newOwner) {
        this.owner = newOwner;
    }

    public void NumShips(int newNumShips) {
        this.numShips = newNumShips;
    }

    public void AddShips(int amount) {
        numShips += amount;
    }

    public void RemoveShips(int amount) {
        numShips -= amount;
    }
    private int planetID;
    private int owner;
    private int numShips;
    private int growthRate;
    private double x, y;
    private HashMap<Integer, Integer> distances;

    private Planet(Planet _p) {
        planetID = _p.planetID;
        owner = _p.owner;
        numShips = _p.numShips;
        growthRate = _p.growthRate;
        x = _p.x;
        y = _p.y;
    }

    public Object clone() {
        return new Planet(this);
    }
}
